package puzzle.common.imgreader;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;

import javax.imageio.ImageIO;

import tomoto.commandline.GetOpt;
import tomoto.io.FileUtil;
import tomoto.util.StrUtil;

public class GenericImgReaderApp {
	private GenericImgReader m_reader;
	private GetOpt m_getopt = new GetOpt("hv:do:");

	public GenericImgReaderApp(ImgPattern[] patterns, String dataSymbols, String visibleSymbols) {
		m_reader = new GenericImgReader(patterns, dataSymbols, visibleSymbols);
	}

	public void run(String[] args) throws IOException {
		m_getopt.parse(args);
		
		if (m_getopt.optionExists("h")) {
			usage();
			return;
		}

		if (m_getopt.getArgs().size() != 1) {
			throw new IllegalArgumentException("Please specify an input file name.");
		}

		if (m_getopt.optionExists("d")) {
			createDistanceImage();
		} else {
			readImage();
		}
	}
	
	private void readImage() throws IOException {
		PrintStream out = getOutputPrintStream();
		File verificationImageFile = getVerificationImageFile();

		String filename = m_getopt.getArgs().get(0);
		InputStream is = new FileInputStream(filename);
		m_reader.readImage(is, out, verificationImageFile);
		is.close();
		out.close();
	}

	private File getVerificationImageFile() {
		File verificationImageFile = null;
		String verificationImageFileName = m_getopt.getOptionalParameter("v");
		if (!StrUtil.isBlank(verificationImageFileName)) {
			verificationImageFile = new File(verificationImageFileName);
		}
		return verificationImageFile;
	}

	private PrintStream getOutputPrintStream() throws FileNotFoundException {
		PrintStream out;
		String outfile = m_getopt.getOptionalParameter("o");
		if (StrUtil.isBlank(outfile)) {
			out = System.out;
		} else {
			out = new PrintStream(new FileOutputStream(outfile));
		}
		return out;
	}

	private void createDistanceImage() throws IOException {
		String fileNameFormat = getDistanceFileNameFoamat();
		String imageFormat = getImageFormat(fileNameFormat);

		String filename = m_getopt.getArgs().get(0);
		InputStream is = new FileInputStream(filename);
		BufferedImage[] images = m_reader.createDistanceImage(is);
		is.close();
		
		for (int i = 0; i < images.length; i++) {
			String file = String.format(fileNameFormat, i);
			ImageIO.write(images[i], imageFormat, new File(file));
		}
	}

	private String getDistanceFileNameFoamat() {
		String outfile = m_getopt.getOptionalParameter("o");
		return StrUtil.isBlank(outfile) ? "distance%d.png" : outfile;
	}

	private String getImageFormat(String fileNameFormat) {
		String format = FileUtil.getSuffix(fileNameFormat);
		return StrUtil.isBlank(format) ? "png" : format;
	}

	private void usage() {
		System.out.println("Arguments:");
		System.out.println("(1) -h");
		System.out.println("(2) [-o <out file>] [-v <verification image>] <input image>");
		System.out.println("(3) -d [-o <out file (use %d)>] <input image>");
	}

}
